
//
//	Cross-browser detection and implementations
//
//-------------------------------------------------------------------------------------------------

var xb = {
	
	Browser: {
		IE: Boolean(window.ActiveXObject)
	},
	
	Function: {
		support: {
			
			bind: Boolean(Function.prototype.bind)
			
		}
	},
	
	Math: {
		PI2: Math.PI * 2,
		KAPPA: 0.552284,
		DEG2RAD: 0.017453293,
		RAD2DEG: 57.2957795,
		
		roundTo: function(n, d) {
			d = isNaN(d) || d < 1 ? 1 : Math.pow(10, d);
    		return Math.round(n * d) / d;
		}
	},
	
	Object: {
		support: {
			
			defineProperty: (function() {
				try { Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'a', {}), 'a'); }
				catch(e) { return false; }
				return true;
			}()),
			
			getterSetter: Boolean(
				Object.__defineGetter__ &&
				Object.__defineSetter__ &&
				Object.__lookupGetter__ &&
				Object.__lookupSetter__
			)
			
		}
	},
	
	Element: {
		id: 0,
		prefix: 'cove_',
		
		support: {
		
			explorerEvents: Boolean(
				Element.prototype.attactEvent &&
				Element.prototype.detatchEvent
			)
		
		}
		
	},
	
	SVG: {
		namespace: 'http://www.w3.org/2000/svg',
		version: '1.1',
		
		// http://stackoverflow.com/questions/654112/how-do-you-detect-support-for-vml-or-svg-in-a-browser
		support: document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1')
	}
	
};


//
//	xb.Object:
//
//		defineProperty
//		lookupProperty
//		defineConstant
//
//-------------------------------------------------------------------------------------------------

//	Getters & setters
//-------------------------------------------------------------------------------------------------

if(xb.Object.support.getterSetter) {
	
	xb.Object.defineProperty = function(prop, desc) {
		if(desc.hasOwnProperty('value')) {
			this[prop] = desc.value;
		} else {
			if(typeof desc.get == 'function') this.__defineGetter__(prop, desc.get);
			if(typeof desc.set == 'function') this.__defineSetter__(prop, desc.set);
		}
	};
	
	xb.Object.lookupProperty = function(prop) {
		if(this.hasOwnProperty(prop)) {
			var g = this.__lookupGetter__(prop),
				s = this.__lookupSetter__(prop);
			if(g || s) {
				return {get: g, set: s};
			} else {
				return {value: this[prop]};
			}
		}
	};
	
} else if(xb.Object.support.defineProperty) {
	
	xb.Object.defineProperty = function(prop, desc) {
		desc.enumerable = true;
		desc.configurable = true;
		if(desc.hasOwnProperty('value')) desc.writable = true;
		Object.defineProperty(this, prop, desc);
	};
	
	xb.Object.lookupProperty = function(prop) {
		return Object.getOwnPropertyDescriptor(this, prop);
	};
	
}


//	Constants
//-------------------------------------------------------------------------------------------------

if(xb.Object.support.defineProperty) {
	xb.Object.defineConstant = function(prop, value) {
		Object.defineProperty(this, prop, {value: value});
	};
} else if(xb.Object.support.getterSetter) {
	xb.Object.defineConstant = function(prop, value) {
		this.__defineGetter__(prop, function() { return value; });
	};
}


//
//	Element.prototype:
//
//		addEventListener
//		setAttributes
//		create
//
//-------------------------------------------------------------------------------------------------

if(xb.Element.support.explorerEvents) {
	xb.Element.addEventListener = function(type, listener, capture) {
		this.addEvent(type, listener);
	};
} else {
	xb.Element.addEventListener = Element.prototype.addEventListener;
}

xb.Element.setAttributes = (function() {
	var reg = /[A-Z]/g, rep = '-$&';
	return function(properties) {
		var i, a;
		for(i in properties) {
			a = i.replace(reg, rep).toLowerCase();
			if(properties[i] === undefined || properties[i] == null)
				this.removeAttribute(a);
			else
				this.setAttribute(a, properties[i]);
		}
	};
}());

xb.Element.appendAttribute = function(prop, value) {
	var v = this.getAttribute(prop);
	this.setAttribute(prop, v ? v + '' + value : value);
};

xb.Element.removeChildren = function() {
    while(this.childNodes.length) {
        this.removeChild(this.firstChild);       
    }
};


//
//	SVG:
//
//		create
//
//-------------------------------------------------------------------------------------------------

xb.SVG.create = function(type, properties) {
	var svg = document.createElementNS(xb.SVG.namespace, type);
	if(type == 'svg') {
		svg.setAttribute('id', xb.Element.prefix + (xb.Element.id++));
		svg.setAttribute('version', xb.SVG.version);
	}
	if(properties) xb.Element.setAttributes.call(svg, properties);
	return svg;
};
